/// <reference path="../_all.ts" />

module Application.Controllers {

    export class ServerController implements Application.Interfaces.Controllers.IController {

        _server_id: number;
        _server_master: Application.Resources.IServer;
        _timeout_id: any;
        _timeout_delay: number;

        public static $inject = [
            '$rootScope',
            '$scope',
            '$location',
            '$routeParams',
            '$timeout',
            'ServerService',
            'ConfigService',
            'TranslationService',
        ];

        public CanStart: boolean;
        public CanStop: boolean;
        public CanUpdate: boolean;

        serverResult: {
            (data): void;
            (data, err): void;
        };

        statusResult: {
            (data): void;
            (data, err): void;
        };

        actionResult: {
            (data): void;
            (data, err): void;
        };

        addConfigResult: {
            (data): void;
            (data, err): void;
        };

        deleteConfigResult: {
            (data): void;
            (data, err): void ;
        };

        applyConfigResult: {
            (data): void;
            (data, err): void;
        };

        refreshServer: {
            (): void;
        };

        constructor(public RootScope: Application.Interfaces.Scopes.IRootScope,
                    public Scope: Application.Interfaces.Scopes.IServerScope,
                    public Location: ng.ILocationService,
                    public RouteParams: Application.Interfaces.Routing.IServerRouteParams,
                    public TimeOut: ng.ITimeoutService,
                    public Server: Application.Interfaces.Services.IServerService,
                    public Configs: Application.Interfaces.Services.IConfigService,
                    public Translations: Application.Interfaces.Services.ITranslationService) {

            this.Scope.vm = this;
            this.CanStart = false;
            this.CanStop = false;
            this.CanUpdate = false;
            this.Scope.user = this.RootScope.user;
            this.Scope.location = this.Location;
            this.Scope.messages = new Application.Utility.Messages();
            this.Scope.navigations = new Application.Utility.Navigations();
            this.Scope.server = <Application.Resources.IServer>{};
            this.Scope.newconfig = <Application.Resources.IConfig>{};
            this.Scope.configChanged = false;
            this._server_id = this.RouteParams.server_id;
            this._timeout_delay = 3500;

            this.Scope.newconfig.server_id = this._server_id;

            this.Scope.navigations.AddLink(Translations.Translate("SERVERLIST"), "/servers", false, false, Application.Constants.Icons.Servers);
            this.Scope.navigations.AddLink(Translations.Translate("SERVER"), "/server/" + this._server_id, true, false, Application.Constants.Icons.Server);
            this.Scope.navigations.AddLink(Translations.Translate("SERVERACTIONS"), "/actions/" + this._server_id, false, true, Application.Constants.Icons.Actions);
            this.Scope.navigations.AddLink(Translations.Translate("SERVERRIGHTS"), "/members/" + this._server_id, false, true, Application.Constants.Icons.Rights);
            if (this.Scope.user && this.Scope.user.role && this.Scope.user.role >= 2) {
                this.Scope.navigations.AddLink(Translations.Translate("PLAYERS"), "/players", false, false, Application.Constants.Icons.Bans);
            };
            if (this.Scope.user && this.Scope.user.role && this.Scope.user.role >= 8) {
                this.Scope.navigations.AddLink(Translations.Translate("USERS"), "/users", false, false, Application.Constants.Icons.Users);
            };
            this.Scope.navigations.AddLinkRight(Translations.Translate("ACCOUNT"), "/users/" + this.Scope.user.user_id, false);
            this.Scope.navigations.AddLinkRight(Translations.Translate("LOGOUT"), "/", false);

            this.Scope.$on("$destroy", () => {
                this._server_id = null;
                if (this._timeout_id != null) {
                    this.TimeOut.cancel(this._timeout_id);
                };
            });

            this.serverResult = (data, err?) => {
                this.serverResultProxy.apply(this, [data, err]);
            };

            this.statusResult = (data, err?) => {
                this.statusResultProxy.apply(this, [data, err]);
            };

            this.actionResult = (data, err?) => {
                this.actionResultProxy.apply(this, [data, err]);
            };

            this.addConfigResult = (data, err?) => {
                this.addConfigResultProxy.apply(this, [data, err]);
            };

            this.deleteConfigResult = (data, err?) => {
                this.deleteConfigResultProxy.apply(this, [data, err]);
            };

            this.applyConfigResult = (data, err?) => {
                this.applyConfigResultProxy.apply(this, [data, err]);
            };

            this.refreshServer = () => {
                this.refreshServerProxy.apply(this);
            };

            if (this._server_id > 0) {
                this._timeout_id = this.TimeOut(this.refreshServer, this._timeout_delay);
            };
            this.getServerWithConfig();
        }

        public log(msg: string) {
            //console.log(msg);
        }

        refreshServerProxy() {
            if (this._server_id != null) {
                this.log('refreshServer: ' + this._server_id);
                this.Server.GetServer(this._server_id, this.statusResult);
                this.TimeOut(this.refreshServer, this._timeout_delay);
            } else {
                this.log('refreshServer: No Server ID: ' + this._server_id);
            };
        }

        public getServer() {
            if (this._server_id != null) {
                this.log('getServer: ' + this._server_id);
                this.Server.GetServer(this._server_id, this.statusResult);
            } else {
                this.Scope.messages.AddAndGrowl(Application.Utility.MessageType.error, "Error", this.Translations.Translate('NOSERVERID'));
            };
        }

        public getServerWithConfig() {
            if (this._server_id != null) {
                console.log('getServerWithConfig: ' + this._server_id);
                this.Server.GetServerWithConfig(this._server_id, this.serverResult);
            } else {
                this.Scope.messages.AddAndGrowl(Application.Utility.MessageType.error, "Error", this.Translations.Translate('NOSERVERID'));
            };
        }

        private serverResultProxy(data, err) {
            this.log('server result');
            if (data != null) {
                var server = <Application.Resources.IServer> data;
                if (server != null) {
                    Application.Resources.ServerUtility.fixBooleans(server);
                    if (server.configs && server.configs.length > 0) {
                        for (var i = 0; i < server.configs.length; i++) {
                            Application.Resources.ConfigUtility.fixBooleans(server.configs[i]);
                        };
                    };
                    this._server_master = angular.copy(server);
                    this.Scope.server = server;
                    this.updateServerStatus(server);
                    this.Scope.messages.AddAndGrowl(Application.Utility.MessageType.info, 'Status', this.Translations.Translate('SERVERINFOLOADED'));
                } else {
                    this.Scope.messages.AddAndGrowl(Application.Utility.MessageType.error, 'Error', this.Translations.Translate('SERVERNOTFOUND'));
                };
            } else {
                if (err != null) {
                    this.Scope.messages.AddAndGrowl(Application.Utility.MessageType.error, err.data.status + ' ' + err.data.type, err.data.message);
                } else {
                    this.Scope.messages.AddAndGrowl(Application.Utility.MessageType.error, '000 Unknown', this.Translations.Translate('UNKNOWNERROR'));
                };
            };
        }

        private statusResultProxy(data, err) {
            this.log('status result');
            if (data != null) {
                var server = <Application.Resources.IServer> data;
                if (server != null) {
                    Application.Resources.ServerUtility.fixBooleans(server);
                    this.updateServerStatus(server);
                } else {
                    this.Scope.messages.AddAndGrowl(Application.Utility.MessageType.error, 'Error', this.Translations.Translate('SERVERNOTFOUND'));
                };
            } else {
                if (err != null) {
                    this.Scope.messages.AddAndGrowl(Application.Utility.MessageType.error, err.data.status + ' ' + err.data.type, err.data.message);
                } else {
                    this.Scope.messages.AddAndGrowl(Application.Utility.MessageType.error, '000 Unknown', this.Translations.Translate('UNKNOWNERROR'));
                };
            };
        }

        private actionResultProxy(data, err) {
            this.log('status result');
            if (data != null) {
                var server = <Application.Resources.IServer> data;
                if (server != null) {
                    this.Scope.messages.AddAndGrowl(Application.Utility.MessageType.success, 'Success', this.Translations.Translate('ACTIONQUEUED'));
                    this.getServer();
                } else {
                    this.Scope.messages.AddAndGrowl(Application.Utility.MessageType.error, 'Error', this.Translations.Translate('ACTIONFAILED'));
                };
            } else {
                if (err != null) {
                    this.Scope.messages.AddAndGrowl(Application.Utility.MessageType.error, err.data.status + ' ' + err.data.type, err.data.message);
                } else {
                    this.Scope.messages.AddAndGrowl(Application.Utility.MessageType.error, '000 Unknown', this.Translations.Translate('UNKNOWNERROR'));
                };
            };
        }

        private updateServerStatus(newServer: Application.Resources.IServer) {
            this.Scope.server.is_started = newServer.is_started;
            this.Scope.server.is_starting = newServer.is_starting;
            this.Scope.server.is_stopped = newServer.is_stopped;
            this.Scope.server.is_stopping = newServer.is_stopping;
            this.Scope.server.is_updating = newServer.is_updating;
            this.CanStart = this.Scope.server.is_stopped && !this.Scope.server.is_starting;
            this.CanStop = this.Scope.server.is_started && !this.Scope.server.is_starting && !this.Scope.server.is_updating;
            this.CanUpdate = this.Scope.server.is_stopped && !this.Scope.server.is_starting;
            this.Scope.server.last_datetime = newServer.last_datetime;
        }

        public addConfig() {
            if (this._server_id != null) {
                this.log('addConfig: ' + this._server_id);

                this.Scope.newconfig.server_id = this._server_id;
                this.Scope.newconfig.desc = this.Scope.newconfig.name;
                this.Scope.newconfig.is_active = true;
                this.Scope.newconfig.is_visible = true;
                this.Scope.newconfig.is_writable = true;

                this.Configs.SaveConfig(this.Scope.newconfig, this.addConfigResult);
            } else {
                this.Scope.messages.AddAndGrowl(Application.Utility.MessageType.error, "Error", this.Translations.Translate('NOSERVERID'));
            };
        }

        private addConfigResultProxy(data, err) {
            this.log('add config result');
            if (data != null) {
                var config = <Application.Resources.IConfig> data;
                if (config != null) {
                    Application.Resources.ConfigUtility.fixBooleans(config);
                    this._server_master.configs.push(config);
                    this.Scope.server.configs.push(config);
                    this.Scope.messages.AddAndGrowl(Application.Utility.MessageType.success, 'Success', new Application.Utility.String(this.Translations.Translate('CONFIGADDED')).format(config.name));
                } else {
                    this.Scope.messages.AddAndGrowl(Application.Utility.MessageType.error, 'Error', this.Translations.Translate('CONFIGNOTADDED'));
                };
            } else {
                if (err != null) {
                    this.Scope.messages.AddAndGrowl(Application.Utility.MessageType.error, err.data.status + ' ' + err.data.type, err.data.message);
                } else {
                    this.Scope.messages.AddAndGrowl(Application.Utility.MessageType.error, '000 Unknown', this.Translations.Translate('UNKNOWNERROR'));
                };
            };
        }

        public deleteConfig(id: number) {
            if (this._server_id != null) {
                this.log('deleteConfig: ' + this._server_id);
                if (id && id > 0) {
                    this.Configs.DeleteConfig(id, this.deleteConfigResult);
                };
            } else {
                this.Scope.messages.AddAndGrowl(Application.Utility.MessageType.error, "Error", this.Translations.Translate('NOSERVERID'));
            };
        }

        private deleteConfigResultProxy(data, err) {
            this.log('delete config result');
            if (data != null) {
                var config = <Application.Resources.IConfig> data;
                if (config != null && config.config_id && config.config_id > 0) {
                    for (var i = 0; i < this._server_master.configs.length; i++) {
                        if (this._server_master.configs[i].config_id == config.config_id) {
                            this._server_master.configs.splice(i, 1);
                            break;
                        };
                    };
                    for (var i = 0; i < this.Scope.server.configs.length; i++) {
                        if (this.Scope.server.configs[i].config_id == config.config_id) {
                            this.Scope.messages.AddAndGrowl(Application.Utility.MessageType.success, 'Success', new Application.Utility.String(this.Translations.Translate('CONFIGDELETED')).format(this.Scope.server.configs[i].name, config.config_id.toString()));
                            this.Scope.server.configs.splice(i, 1);
                            this.TimeOut(
                                this.Scope.$apply
                            );
                            break;
                        };
                    };
                } else {
                    this.Scope.messages.AddAndGrowl(Application.Utility.MessageType.error, 'Error', this.Translations.Translate('CONFIGNOTDELETED'));
                };
            } else {
                if (err != null) {
                    this.Scope.messages.AddAndGrowl(Application.Utility.MessageType.error, err.data.status + ' ' + err.data.type, err.data.message);
                } else {
                    this.Scope.messages.AddAndGrowl(Application.Utility.MessageType.error, '000 Unknown', this.Translations.Translate('UNKNOWNERROR'));
                };
            };
        }

        public changeConfig(id : number) {
            this.Scope.configChanged = true;
        }

        public applyConfig() {
            if (this._server_id != null) {
                this.log('applyConfig: ' + this._server_id);
                this.Configs.SaveServerConfig(this._server_id, this.Scope.server.configs, this.applyConfigResult);
            } else {
                this.Scope.messages.AddAndGrowl(Application.Utility.MessageType.error, "Error", this.Translations.Translate('NOSERVERID'));
            };
        }

        private applyConfigResultProxy(data, err) {
            this.log('add config result');
            if (data != null) {
                var configs = <Application.Resources.IConfig[]> data;
                if (configs != null) {
                    for (var i = 0; i < configs.length; i++) {
                        Application.Resources.ConfigUtility.fixBooleans(configs[i]);
                    };
                    this._server_master.configs = configs;
                    this.resetConfig();
                    this.Scope.messages.AddAndGrowl(Application.Utility.MessageType.success, 'Success', this.Translations.Translate('ALLCHANGESSAVED'));
                } else {
                    this.Scope.messages.AddAndGrowl(Application.Utility.MessageType.error, 'Error', this.Translations.Translate('ERRORSAVINGCHANGES'));
                };
            } else {
                if (err != null) {
                    this.Scope.messages.AddAndGrowl(Application.Utility.MessageType.error, err.data.status + ' ' + err.data.type, err.data.message);
                } else {
                    this.Scope.messages.AddAndGrowl(Application.Utility.MessageType.error, '000 Unknown', this.Translations.Translate('UNKNOWNERROR'));
                };
            };
        }

        public resetConfig() {
            if (this._server_id != null) {
                this.log('resetConfig: ' + this._server_id);
                var last = 0;
                for (var i = 0; i < this.Scope.server.configs.length; i++) {
                    for (var j = last; j < this._server_master.configs.length; j++) {
                        if (this.Scope.server.configs[i].config_id == this._server_master.configs[j].config_id) {
                            last = j;
                            $('#config_' + this._server_master.configs[j].config_id).val(this._server_master.configs[j].value);
                            break;
                        };
                    };
                };
                this.Scope.configsForm.$setPristine();
            } else {
                this.Scope.messages.AddAndGrowl(Application.Utility.MessageType.error, "Error", this.Translations.Translate('NOSERVERID'));
            };
        }

        public actionStart() {
            if (this._server_id != null) {
                this.log('actionStart: ' + this._server_id);
                this.Server.PostServerAction(this._server_id, 'start', this.actionResult);
            } else {
                this.Scope.messages.AddAndGrowl(Application.Utility.MessageType.error, "Error", this.Translations.Translate('NOSERVERID'));
            };
        }

        public actionStop() {
            if (this._server_id != null) {
                this.log('actionStop: ' + this._server_id);
                this.Server.PostServerAction(this._server_id, 'stop', this.actionResult);
            } else {
                this.Scope.messages.AddAndGrowl(Application.Utility.MessageType.error, "Error", this.Translations.Translate('NOSERVERID'));
            };
        }

        public actionUpdate() {
            if (this._server_id != null) {
                this.log('actionUpdate: ' + this._server_id);
                this.Server.PostServerAction(this._server_id, 'update', this.actionResult);
            } else {
                this.Scope.messages.AddAndGrowl(Application.Utility.MessageType.error, "Error", this.Translations.Translate('NOSERVERID'));
            };
        }

    };
}